C#(.NET)でJsonの操作はJsonSerializerを使いましょう
概要
以前、C#(.NET)にはJsonフォーマットを操作するライブラリが完備されなかったため、3rd partyのライブラリはよく使われる気がします(例えばNewtonSoftのJson.NETライブラリ)。最近、C#のデフォルトJson操作ライブラリが使いやすくなっているようですので、できればスタンダードのライブラリを使うべきだと思ってます。
テスト環境
- System : Windows 10 (.NET 5)
- Editor : VSCode
プロジェクトの作成
コマンドラインツール(cmdなど)で下記のコマンドを使って新しいTest
というプロジェクトが作成されます。
dotnet new console -n Test
名前空間を宣言する
これから使う名前空間を先に宣言します。
// Created by default, you can delete this line if you want using System; // For File, FileStream, StreamWriter, StreamReader using System.IO; // For Json Serialization and Deserialization using System.Text.Json; using System.Text.Json.Serialization; // We use List<T> to contain student information objects using System.Collections.Generic;
データのクラスを定義する(例:学生個人情報)
// Define a simple student class with basic parameters and constructor public class Student { public string Name { get; set; } = string.Empty; public string ID { get; set; } = string.Empty; public int Age { get; set; } = 0; public Student(string name, string id, int age) { Name = name; ID = id; Age = age; } }
DataをClassにし、JsonSerializerでSerializeする
static void WriteJson() { // Create a list container for student information List<Student> list = new List<Student>(); // Adding student information into list list.Add(new Student("Sakamoto", "A002", 12)); list.Add(new Student("John", "B013", 15)); list.Add(new Student("Lucy", "C024", 13)); // Make JsonSerializer not to escape non-ASCII character(like Japanese characters). // If you use English only, the "options" parameter is not needed. JsonSerializerOptions options = new JsonSerializerOptions() { Encoder = System.Text.Encodings.Web.JavaScriptEncoder. Create(System.Text.Unicode.UnicodeRanges.All)}; // Create a new file and get the FileStream in a "using" scope using (FileStream fileStream = File.Create("StudentInfo.json")) { // Create a StreamWriter for the FileStream in a "using" scope using (StreamWriter writer = new StreamWriter(fileStream, System.Text.Encoding.UTF8)) { // Write student information into file in a loop foreach (var student in list) { // Serialize student information. If the internal string members are English only, the "options" is not needed. string str = JsonSerializer.Serialize<Student>(student, options); writer.WriteLine(str); } // Extra explanation : // It's safer to use a using scope here, // since both FileStream and StreamWriter expicitly implement "IDisposable" interface, // which "freeing, releasing, or resetting unmanaged resources" (async version : IAsyncDisposable/DisposeAsync). // // The "using" scope helps dealing with Dispose() automatically (even when an exception is thrown), // because it is translated to try{} finally{x.Dispose()} in compiler. } } }
// Create a list container for student information List<Student> list = new List<Student>(); // Adding student information into list list.Add(new Student("Sakamoto", "A002", 12)); list.Add(new Student("John", "B013", 15)); list.Add(new Student("Lucy", "C024", 13));
学生個人情報用のリストを作って、学生情報を作りながらリストに入れる。
JsonSerializerOptions options = new JsonSerializerOptions() { Encoder = System.Text.Encodings.Web.JavaScriptEncoder. Create(System.Text.Unicode.UnicodeRanges.All)};
すべての文字をそのまま保存します。
JsonSerializerはASCIIじゃない文字を勝手に\uxxxのようにUnicodeデータとして書き換えます。英語は問題ないですが、日本語などの文字を読めるように保存したい場合はこの行のoptions
が必要です。
using (FileStream fileStream = File.Create("StudentInfo.json"))
学生個人情報のJsonファイルを作成します。
using (StreamWriter writer = new StreamWriter(fileStream, System.Text.Encoding.UTF8))
Jsonファイルにデータを書き込むライター(念のためUTF8
を指定する)を定義します。
string str = JsonSerializer.Serialize<Student>(student, options); writer.WriteLine(str);
JsonSerializerのドキュメンテーションはこちら:JsonSerializer Class Doc
生徒の情報をSerialize()
し、返した文字列をStreamWriter
経由Jsonファイルに書き込みます。(英語以外の言語文字じゃなければ、先に定義したoptions
をいれなくても大丈夫です。)
JsonSerializerOptionsはいろんなオプションがあるので、ドキュメンテーションを参考してください:JsonSerializerOptions Doc
プロジェクトパスにコマンドラインツールでdotnet run
を実行したら、同じパスにStudentInfo.json
というファイルが作られて、中身はこういう感じ:
{"Name":"Sakamoto","ID":"A002","Age":12} {"Name":"John","ID":"B013","Age":15} {"Name":"Lucy","ID":"C024","Age":13}
JsonファイルのデータをJsonSerializerでDeserializeして、プリントする
static void ReadJson() { // Open json file and get the FileStream in a "using" scope using (FileStream fileStream = File.OpenRead("StudentInfo.json")) { // Create a StreamReader for the FileStream in a "using" scope using (StreamReader reader = new StreamReader(fileStream, System.Text.Encoding.UTF8)) { // Operate in a while loop, which checks if it reaches the end of the stream while (!reader.EndOfStream) { // Deserialize data from line by line and print it Student student = JsonSerializer.Deserialize<Student>(reader.ReadLine()); Console.WriteLine($"Name:{student.Name}, ID:{student.ID}, Age:{student.Age}"); } } } }
using (FileStream fileStream = File.OpenRead("StudentInfo.json"))
先ほど作ったStudentInfo.json
を開いて、それのFileStream
をもらいます。
using (StreamReader reader = new StreamReader(fileStream, System.Text.Encoding.UTF8))
Jsonファイルにデータを読みだすリーダー(念のためUTF8
を指定する)を定義します。
while (!reader.EndOfStream)
読み終わったかどうかをループでチェックします。
Student student = JsonSerializer.Deserialize<Student>(reader.ReadLine()); Console.WriteLine($"Name:{student.Name}, ID:{student.ID}, Age:{student.Age}");
最後は、DeserializeしたデータをStudent
クラスオブジェクトに返して、中身をプリントします。プリントした結果はこんな感じ:
Name:Sakamoto, ID:A002, Age:12 Name:John, ID:B013, Age:15 Name:Lucy, ID:C024, Age:13
まとめ
JsonSerializer
クラスを使って、データを簡単に整えたり、操作できます。StreamWriter
やStreamReader
なども活用し、やれることが多くなる気がします。そしてJsonSerializerOptions
でカスタマイズできるオプションも多いし、更に自由度がありそうです。C#(.NET)でJsonSerializerを使って普通のデータ、I/O処理などは楽だと思います。